//
//  FQDFeedCacheItem.m
//  FakeQDaily
//
//  Created by mewxiv on 8/18/16.
//  Copyright © 2016 Xensius. All rights reserved.
//

#import "FQDFeedCacheItem.h"
#import "FQDDatabase.h"

static NSString *const kPrimaryKeyName = @"fqd_pid";
static NSString *const kFeedIdName = @"fqd_feed_id";
static NSString *const kCursorKeyName = @"fqd_cursor_key";
static NSString *const kLastCursorKeyName = @"last_key";
static NSString *const kLatestCursorKey = @"0";

@interface FQDFeedCacheItem ()

@property (nonatomic, strong) NSString *cacheId;
@property (nonatomic, assign) BOOL didSetupCache;
@property (nonatomic, assign) BOOL isOldFeed;

@end

@implementation FQDFeedCacheItem

+ (instancetype)cacheWithIdentifier:(NSString *)cacheId
{
    return [[self alloc] initWithIdentifier:cacheId];
}

- (instancetype)initWithIdentifier:(NSString *)cacheId
{
    self = [self init];
    if (self) {
        _cacheId = cacheId;
    }
    return self;
}

- (void)setupWithFeeds:(NSDictionary *)feedsResponse
{
    NSArray *columnNames = [feedsResponse allKeys];
    
    NSMutableDictionary *columns = [NSMutableDictionary dictionary];
    
    for (NSString *columnName in columnNames) {
        id object = feedsResponse[columnName];
        NSString *columnAttribute = @"TEXT";
        if ([object isKindOfClass:[NSDictionary class]] ||
            [object isKindOfClass:[NSArray class]]) {
            columnAttribute = @"BLOB";
        }
        [columns setObject:columnAttribute forKey:columnName];
    }
    
    NSString *const primaryIdName = kPrimaryKeyName;
    NSString *const primaryIdAttribute = @"INTEGER PRIMARY KEY AUTOINCREMENT";
    [columns setObject:primaryIdAttribute forKey:primaryIdName];
    [columns setObject:@"TEXT" forKey:kCursorKeyName];
    [columns setObject:@"TEXT" forKey:kFeedIdName];
    
    FQDDatabase *database = [FQDDatabase sharedDatabase];
    [database createTableIfNotExist:[self feedCacheTableName]
                            columns:columns];
    self.didSetupCache = YES;
}

- (BOOL)isNewFeeds:(NSString *)feedId cursorKey:(NSString *)lastCursorKey
{
    FQDDatabase *database = [FQDDatabase sharedDatabase];
    
    NSString *condition1 =
    [NSString stringWithFormat:@"%@ = '%@'", kCursorKeyName, kLatestCursorKey];
    NSString *condition2 =
    [NSString stringWithFormat:@"%@ = '%@'", kFeedIdName, feedId];
    NSString *condition = [NSString stringWithFormat:@"%@ AND %@", condition1, condition2];
    NSString *oldLastKey = [database selectColumn:kLastCursorKeyName
                                           fromTable:[self feedCacheTableName]
                                     whereCondition:condition];
    return (![oldLastKey isEqualToString:lastCursorKey]);
}

- (void)cacheFeeds:(NSDictionary *)feedsResponse feedId:(NSString *)feedId cursorKey:(NSString *)cursorKey
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
        if (!self.didSetupCache) {
            [self setupWithFeeds:feedsResponse];
        }
    
        FQDDatabase *database = [FQDDatabase sharedDatabase];
        NSString *tableName = [self feedCacheTableName];
        if (cursorKey == kLatestCursorKey) {
            // 判断当前缓存的是否是旧的feeds，是否需要用etag判断？
            NSString *lastCursorKey = feedsResponse[kLastCursorKeyName];
            if ([self isNewFeeds:feedId cursorKey:lastCursorKey]) {
                [database deleteAllFromTable:tableName];
                self.isOldFeed = NO;
            } else {
                self.isOldFeed = YES;
            }
        }
        
        if (!self.isOldFeed) {
            NSDictionary *columnValues = [self columnValuesFromFeeds:feedsResponse
                                                              feedId:feedId
                                                           cursorKey:cursorKey];
            [database insertIntoTable:tableName columnValues:columnValues];
        }
    });
}

- (void)loadFeedsFromCache:(NSString *)feedId cursorKey:(NSString *)cursorKey completion:(void (^)(id))completion
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        FQDDatabase *database = [FQDDatabase sharedDatabase];
        if (![database tableExists:[self feedCacheTableName]]) {
            dispatch_async(dispatch_get_main_queue(), ^{
                completion(nil);
            });
            return;
        }
        
        NSString *condition1 =
        [NSString stringWithFormat:@"%@ = '%@'", kCursorKeyName, cursorKey];
        NSString *condition2 =
        [NSString stringWithFormat:@"%@ = '%@'", kFeedIdName, feedId];
        NSString *condition = [NSString stringWithFormat:@"%@ AND %@", condition1, condition2];
        NSString *allColumnPlaceHolder = @"*";
        NSArray *results = [database selectColumns:@[ allColumnPlaceHolder ]
                                         fromTable:[self feedCacheTableName]
                                    whereCondition:condition];
        id responseObject = nil;
        if ([results count] > 0) {
            responseObject = [NSMutableDictionary dictionary];
            
            NSDictionary *resultFeeds = [results firstObject];
            for (NSString *columnName in resultFeeds) {
                id jsonData = resultFeeds[columnName];
                id jsonObject = nil;
                // 把NSData还原为json字典和数组
                if ([jsonData isKindOfClass:[NSData class]]) {
                    jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
                                                                 options:NSJSONReadingAllowFragments
                                                                   error:nil];
                }
                [responseObject setObject:(jsonObject ? : jsonData) forKey:columnName];
            }
            responseObject = [responseObject copy];
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            completion(responseObject);
        });
    });
}

- (NSDictionary *)columnValuesFromFeeds:(NSDictionary *)feedsResponse feedId:(NSString *)feedId cursorKey:(NSString *)cursorKey
{
    NSMutableDictionary *columnValues = [NSMutableDictionary dictionary];
    for (NSString *columnName in feedsResponse) {
        id jsonObject = feedsResponse[columnName];
        id jsonData = nil;
        // 对json字典和数组转换为NSData进行存储
        if ([jsonObject isKindOfClass:[NSDictionary class]] ||
            [jsonObject isKindOfClass:[NSArray class]]) {
            jsonData = [NSJSONSerialization dataWithJSONObject:jsonObject
                                  options:0 error:nil];
        }
        [columnValues setObject:(jsonData ? : jsonObject) forKey:columnName];
    }
    [columnValues setObject:feedId forKey:kFeedIdName];
    [columnValues setObject:cursorKey forKey:kCursorKeyName];
    return columnValues;
}

- (BOOL)hasCacheForFeedId:(NSString *)feedId cursorKey:(NSString *)cursorKey
{
    FQDDatabase *database = [FQDDatabase sharedDatabase];
    if (![database tableExists:[self feedCacheTableName]]) {
        return NO;
    }
    
    NSString *condition1 =
    [NSString stringWithFormat:@"%@ = '%@'", kCursorKeyName, cursorKey];
    NSString *condition2 =
    [NSString stringWithFormat:@"%@ = '%@'", kFeedIdName, feedId];
    NSString *condition = [NSString stringWithFormat:@"%@ AND %@", condition1, condition2];
    NSString *result = [database selectColumn:@"1"
                                        fromTable:[self feedCacheTableName]
                                   whereCondition:condition];
    return (result != nil);
}


- (NSString *)feedCacheTableName
{
    return [NSString stringWithFormat:@"fqd_cache_%@", self.cacheId];
}

@end
